package com.xiaobias.a47;

import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

@Configuration
@SuppressWarnings("all")
public class A47_3 {

    public static void main(String[] args) throws Exception {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A47_3.class);
        DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();

        System.out.println(">>>>>>>>>>>>>>>>>>>>>>> 6. @Primary");
//        testPrimary(beanFactory);
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>> 7. Default");
        testDefault(beanFactory);
    }

    private static void testDefault(DefaultListableBeanFactory factory) throws Exception {
        DependencyDescriptor dd1 = new DependencyDescriptor(Target3.class.getDeclaredField("service3"), true);
        Class<?> type = dd1.getDependencyType();
        String[] names = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(factory, type);
        for (String name : names) {
            if (name.equals(dd1.getDependencyName())) {
                System.out.println(name);
            }
        }
    }

    private static void testPrimary(DefaultListableBeanFactory factory) throws Exception {
        DependencyDescriptor dd1 = new DependencyDescriptor(Target2.class.getDeclaredField("service"), true);
        Class<?> type = dd1.getDependencyType();
        String[] names = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(factory, type);
        for (String name : names) {
            BeanDefinition bd = factory.getMergedBeanDefinition(name);
            if (factory.getMergedBeanDefinition(name).isPrimary()) {
                System.out.println(name);
            }
        }
    }

    static class Target2 {
        @Autowired private Service service;
    }
    static class Target3 {
        @Autowired private Service service3;
    }

    interface Service {}
    @Component("service1") static class Service1 implements Service {}
    @Component("service2") @Primary static class Service2 implements Service {}
    @Component("service3") static class Service3 implements Service {}

}
